<!doctype html>
<html lang="zh"><head>
<title>es6-Reflect相关 - 糖羽仙</title>
<meta charset="UTF-8">
<meta name="keywords" content="blog ACG JavaScript VUE IT">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">

<link rel="shortcut icon" href="/images/head/head.jpg" type="image/jpeg" />
<meta name="description" content="ES6 为了操作对象而提供的新API,未来的新方法将只部署在Reflect对象上！">
<meta property="og:type" content="article">
<meta property="og:title" content="es6-Reflect相关">
<meta property="og:url" content="https://www.tangyuxian.com/2021/06/10/%E5%89%8D%E7%AB%AF/es6/es6-Reflect%E7%9B%B8%E5%85%B3/index.html">
<meta property="og:site_name" content="糖羽仙">
<meta property="og:description" content="ES6 为了操作对象而提供的新API,未来的新方法将只部署在Reflect对象上！">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-06-10T08:01:41.000Z">
<meta property="article:modified_time" content="2022-08-20T10:06:06.031Z">
<meta property="article:author" content="tangyuxian">
<meta property="article:tag" content="转载">
<meta property="article:tag" content="es6">
<meta name="twitter:card" content="summary">

<link rel="stylesheet" href="/lib/fancybox/fancybox.css">
<link rel="stylesheet" href="/lib/mdui_043tiny/mdui.css">


<link rel="stylesheet" href="/lib/iconfont/iconfont.css?v=1763992124118">

    <link rel="stylesheet" href="//at.alicdn.com/t/font_2421060_8z08qcz5sq3.css">

<link rel="stylesheet" href="/css/style.css?v=1763992124118">




    
        <link rel="stylesheet" href="/custom.css?v=1763992124118">
    
        <link rel="stylesheet" href="/themes/umaru/index.css?v=1763992124118">
    
        <link rel="stylesheet" href="/themes/asuka/index.css?v=1763992124118">
    



<script src="/lib/mdui_043tiny/mdui.js" async></script>
<script src="/lib/fancybox/fancybox.umd.js" async></script>
<script src="/lib/lax.min.js" async></script>


<script async src="/js/app.js?v=1763992124118"></script>

 

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-1Z7TFL96ZH"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-1Z7TFL96ZH');
</script>


<link rel="stylesheet"  href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/atom-one-dark.min.css">
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-shiki-plugin@latest/lib/codeblock.css">
<style>:root{--hl-color:#e1e4e8;--hl-bg:#24292e;--hltools-bg:#1f2428;--hltools-color:#c5c5c5;--hlnumber-bg:#24292e;--hlnumber-color:#444d56;--hlscrollbar-bg:#32383e;--hlexpand-bg:linear-gradient(180deg,rgba(36,41,46,0.1),rgba(36,41,46,0.9))}</style><!-- hexo injector head_end end --><meta name="generator" content="Hexo 7.3.0"></head><body class="nexmoe mdui-drawer-body-left"><div id="nexmoe-background"><div class="nexmoe-bg" style="background-image: url(/images/background/xiaomai.jpg)"></div><div class="nexmoe-character"></div><div class="mdui-appbar mdui-shadow-0"><div class="mdui-toolbar"><a class="mdui-btn mdui-btn-icon mdui-ripple" mdui-drawer="{target: &#039;#drawer&#039;, swipe: true}" title="menu"><i class="mdui-icon nexmoefont icon-menu"></i></a><div class="mdui-toolbar-spacer"></div><a class="mdui-btn mdui-btn-icon" href="/" title="tangyuxian"><img src="/images/head/head.jpg" alt="tangyuxian"></a></div></div></div><div id="nexmoe-header"><div class="nexmoe-drawer mdui-drawer" id="drawer">
    <div class="nexmoe-avatar mdui-ripple">
        <a href="/" title="tangyuxian">
            <img src="/images/head/head.jpg" alt="tangyuxian" alt="tangyuxian">
        </a>
    </div>
    <div class="nexmoe-count">
        <div class="nexmoe-count-item"><span>文章</span>84 <div class="item-radius"></div><div class="item-radius item-right"></div> </div>
        <div class="nexmoe-count-item"><span>标签</span>38<div class="item-radius"></div><div class="item-radius item-right"></div></div>
        <div class="nexmoe-count-item"><span>分类</span>5<div class="item-radius"></div><div class="item-radius item-right"></div></div>
    </div>
    <div class="nexmoe-list mdui-list" mdui-collapse="{accordion: true}">
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/" title="回到首页">
            <i class="mdui-list-item-icon nexmoefont icon-meishi"></i>
            <div class="mdui-list-item-content">
                回到首页
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/archives.html" title="文章归档">
            <i class="mdui-list-item-icon nexmoefont icon-hanbao1"></i>
            <div class="mdui-list-item-content">
                文章归档
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/about.html" title="关于糖糖">
            <i class="mdui-list-item-icon nexmoefont icon-jiubei1"></i>
            <div class="mdui-list-item-content">
                关于糖糖
            </div>
        </a>
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/friend.html" title="我的朋友">
            <i class="mdui-list-item-icon nexmoefont icon-cola"></i>
            <div class="mdui-list-item-content">
                我的朋友
            </div>
        </a>
        
    </div>
    
    
        
        <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-search">
         
            <form id="search_form" action_e="https://cn.bing.com/search?q=site:tangyuxian.com" onsubmit="return search();">
                <label><input id="search_value" name="q" type="search" placeholder="搜索"></label>
            </form>
         
    </div>
</div>




    
        
        <div class="nexmoe-widget-wrap">
	<div class="nexmoe-widget nexmoe-social">
		<a
			class="mdui-ripple"
			href="http://wpa.qq.com/msgrd?v=3&uin=2120252100&site=qq&menu=yes"
			target="_blank"
			mdui-tooltip="{content: 'QQ'}"
			style="
				color: rgb(64, 196, 255);
				background-color: rgba(64, 196, 255, .1);
			"
		>
			<i
				class="nexmoefont icon-QQ"
			></i> </a
		><a
			class="mdui-ripple"
			href="mailto:tangyuxian@vip.qq.com"
			target="_blank"
			mdui-tooltip="{content: 'mail'}"
			style="
				color: rgb(249,8,8);
				background-color: rgba(249,8,8,.1);
			"
		>
			<i
				class="nexmoefont icon-mail-fill"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://blog.csdn.net/qq_40621378?type=blog"
			target="_blank"
			mdui-tooltip="{content: 'CSDN'}"
			style="
				color: rgb(199,29,35);
				background-color: rgba(199,29,35,.1);
			"
		>
			<i
				class="nexmoefont icon-csdn"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://www.cnblogs.com/lovetangyuxian/"
			target="_blank"
			mdui-tooltip="{content: '博客园'}"
			style="
				color: rgb(66, 214, 29);
				background-color: rgba(66, 214, 29, .1);
			"
		>
			<i
				class="nexmoefont icon-bokeyuan"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://github.com/tangyuxian/"
			target="_blank"
			mdui-tooltip="{content: 'GitHub'}"
			style="
				color: rgb(25, 23, 23);
				background-color: rgba(25, 23, 23, .15);
			"
		>
			<i
				class="nexmoefont icon-github"
			></i> </a
		><a
			class="mdui-ripple"
			href="https://gitee.com/tangyuxian"
			target="_blank"
			mdui-tooltip="{content: 'gitee'}"
			style="
				color: rgb(255, 255, 255);
				background-color: rgb(199,29,35);
			"
		>
			<i
				class="nexmoefont icon-mayun"
			></i> </a
		>
	</div>
</div>

    
        
        
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">文章分类</h3>
    <div class="nexmoe-widget">

      <ul class="category-list">

        


        

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/其它/">其它</a>
          <span class="category-list-count">2</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/前端/">前端</a>
          <span class="category-list-count">62</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/后端/">后端</a>
          <span class="category-list-count">8</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/开发工具/">开发工具</a>
          <span class="category-list-count">11</span>
        </li>

        

        <li class="category-list-item">
          <a class="category-list-link" href="/categories/服务器端/">服务器端</a>
          <span class="category-list-count">1</span>
        </li>

        
      </ul>

    </div>
  </div>


    
        
        
  <div class="nexmoe-widget-wrap">
    <div id="randomtagcloud" class="nexmoe-widget tagcloud nexmoe-rainbow">
      <a href="/tags/JavaScript/" style="font-size: 15.56px;">JavaScript</a> <a href="/tags/Jetbrains/" style="font-size: 10px;">Jetbrains</a> <a href="/tags/TypeScript/" style="font-size: 10px;">TypeScript</a> <a href="/tags/UI%E5%BA%93/" style="font-size: 13.33px;">UI库</a> <a href="/tags/centos/" style="font-size: 10px;">centos</a> <a href="/tags/css/" style="font-size: 11.11px;">css</a> <a href="/tags/docker/" style="font-size: 10px;">docker</a> <a href="/tags/echarts/" style="font-size: 10px;">echarts</a> <a href="/tags/elementPlus/" style="font-size: 13.33px;">elementPlus</a> <a href="/tags/es6/" style="font-size: 14.44px;">es6</a> <a href="/tags/git/" style="font-size: 13.33px;">git</a> <a href="/tags/github/" style="font-size: 10px;">github</a> <a href="/tags/html/" style="font-size: 10px;">html</a> <a href="/tags/http/" style="font-size: 13.33px;">http</a> <a href="/tags/java/" style="font-size: 11.11px;">java</a> <a href="/tags/markerdown/" style="font-size: 11.11px;">markerdown</a> <a href="/tags/nginx/" style="font-size: 10px;">nginx</a> <a href="/tags/node/" style="font-size: 13.33px;">node</a> <a href="/tags/vite/" style="font-size: 10px;">vite</a> <a href="/tags/vue/" style="font-size: 18.89px;">vue</a> <a href="/tags/webpack/" style="font-size: 10px;">webpack</a> <a href="/tags/xuex/" style="font-size: 10px;">xuex</a> <a href="/tags/%E4%BA%8B%E4%BB%B6%E6%B5%81/" style="font-size: 10px;">事件流</a> <a href="/tags/%E4%BA%92%E8%81%94%E7%BD%91/" style="font-size: 10px;">互联网</a> <a href="/tags/%E5%8A%A0%E5%AF%86/" style="font-size: 12.22px;">加密</a> <a href="/tags/%E5%8E%9F%E5%88%9B/" style="font-size: 20px;">原创</a> <a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size: 13.33px;">工具</a> <a href="/tags/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/" style="font-size: 12.22px;">微信小程序</a> <a href="/tags/%E6%80%BB%E7%BB%93/" style="font-size: 13.33px;">总结</a> <a href="/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" style="font-size: 10px;">数据结构</a> <a href="/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/" style="font-size: 10px;">服务器</a> <a href="/tags/%E6%B5%8F%E8%A7%88%E5%99%A8/" style="font-size: 17.78px;">浏览器</a> <a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size: 14.44px;">算法</a> <a href="/tags/%E7%BC%96%E8%A7%A3%E7%A0%81/" style="font-size: 10px;">编解码</a> <a href="/tags/%E7%BE%8E%E5%8C%96/" style="font-size: 12.22px;">美化</a> <a href="/tags/%E8%A7%86%E9%A2%91/" style="font-size: 11.11px;">视频</a> <a href="/tags/%E8%AE%B0%E5%BD%95/" style="font-size: 11.11px;">记录</a> <a href="/tags/%E8%BD%AC%E8%BD%BD/" style="font-size: 16.67px;">转载</a>
    </div>
    
      <script>
        var maxTagcloud = parseInt(17);
        var tags_length = parseInt(38);
        var tags_arr = [];
        for(var i = 0; i < tags_length; i++){
          tags_arr.push(i);
        }
        tags_arr.sort(function (l, r) {
          return Math.random() > 0.5 ? -1 : 1;
        });
        tags_arr = tags_arr.slice(0, maxTagcloud < tags_length ? tags_length - maxTagcloud : 0);
        for(var tag_i = 0; tag_i < tags_arr.length; tag_i++){
          document.getElementById("randomtagcloud").children[tags_arr[tag_i]].style.display = 'none';
        }
      </script>
    
  </div>

    
        
        
        
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">文章归档</h3>
    <div class="nexmoe-widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2025/">2025</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2023/">2023</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2022/">2022</a><span class="archive-list-count">23</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/">2021</a><span class="archive-list-count">54</span></li></ul>
    </div>
  </div>



    
        
        
  <div class="nexmoe-widget-wrap">
    <h3 class="nexmoe-widget-title">最新文章</h3>
    <div class="nexmoe-widget">
      <ul>
        
          <li>
            <a href="/2025/11/12/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/%E7%BE%8E%E5%8C%96/%E7%BE%8E%E5%8C%96-%E7%BD%91%E9%A1%B5%E4%B8%BB%E9%A2%98%E5%88%87%E6%8D%A2%E7%9A%84%E6%B8%90%E5%8F%98%E5%8A%A8%E7%94%BB/">美化-网页主题切换的渐变动画</a>
          </li>
        
          <li>
            <a href="/2025/09/29/%E5%89%8D%E7%AB%AF/css/css-%E8%A1%A8%E6%A0%BCtd%E4%B8%8B%E9%AB%98%E5%BA%A6%E4%B8%A2%E5%A4%B1%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/">css-表格td下高度丢失解决办法</a>
          </li>
        
          <li>
            <a href="/2025/09/23/%E5%89%8D%E7%AB%AF/vue/vue-%E5%B0%81%E8%A3%85%E5%87%BD%E6%95%B0%E5%BC%8F%E8%A7%A6%E5%8F%91%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95/">vue-封装函数式触发右键菜单组件</a>
          </li>
        
          <li>
            <a href="/2025/06/04/%E5%89%8D%E7%AB%AF/UI%E5%BA%93/UI%E5%BA%93-ElTooltip%E5%8F%AA%E5%9C%A8%E6%96%87%E5%AD%97%E8%B6%85%E5%87%BA%E8%8C%83%E5%9B%B4%E6%97%B6%E6%98%BE%E7%A4%BA%E7%9A%84%E8%A7%86%E7%BA%BF%E6%96%B9%E5%BC%8F/">UI库-ElTooltip只在文字超出范围时显示的视线方式</a>
          </li>
        
          <li>
            <a href="/2025/05/29/%E5%89%8D%E7%AB%AF/UI%E5%BA%93/UI%E5%BA%93-%E5%B0%81%E8%A3%85PageTable%E6%80%BB%E8%A7%88/">UI库-封装PageTable总览</a>
          </li>
        
      </ul>
    </div>
  </div>

    
        
        <div class="nexmoe-widget-wrap">
    <div class="nexmoe-widget nexmoe-link">
		<ul>
        
            <li>
                <a href="https://tangyuxian.com/" target="_blank" >
                    <img src="https://cdn.tangyuxian.com/PicGoImages/202304272004917.jpg" alt="糖糖第一可爱"></img>
                    <p style="color: var(--color-primary)">糖糖第一可爱</p>
                </a>
            </li>
        
		</ul>
    </div>
</div>
<style>
.nexmoe-widget-wrap .nexmoe-link ul li a {
    text-align : center;
}
.nexmoe-widget-wrap .nexmoe-link ul li a img {
    max-width : 100%;
}
.nexmoe-widget-wrap .nexmoe-link ul li a p {
    margin: 10px 0;
}
</style>

    
   
    <div class="nexmoe-copyright">
        &copy; 2025 tangyuxian
        Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
        & <a href="https://github.com/tangyuxian/hexo-theme-tangyuxian" target="_blank">Tangyuxian</a>
        <br><a target="_blank" href="https://beian.miit.gov.cn/">辽ICP备2021002341号</a>
<div style="font-size: 12px">
   <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
   本站总访问量  <a id="busuanzi_value_site_pv"></a> 次<br />
   本站访客数<a id="busuanzi_value_site_uv"></a>人次
</div>

    </div>
</div><!-- .nexmoe-drawer --></div><div id="nexmoe-content"><div class="nexmoe-primary"><div class="nexmoe-post">
  <article>
    
        <div class="nexmoe-post-cover">
            <img src="/images/post/es6.jpg" alt="es6-Reflect相关" loading="lazy">
            <h1>es6-Reflect相关</h1>
        </div>
        
    
    <div class="nexmoe-post-meta">
    <div class="nexmoe-rainbow">
        <a class="nexmoefont icon-calendar-fill">2021年06月10日</a>
        
            <a class="nexmoefont icon-appstore-fill -link" href="/categories/%E5%89%8D%E7%AB%AF/">前端</a>
        
        
    </div>
    
    
    
    
    
</div>

    <p>ES6 为了操作对象而提供的新API,未来的新方法将只部署在Reflect对象上！</p>
<span id="more"></span>

<p><code>Reflect</code>对象与<code>Proxy</code>对象一样，也是 ES6 为了操作对象而提供的新 API。<code>Reflect</code>对象的设计目的有这样几个。</p>
<h2 id="1-概述"><a href="#1-概述" class="headerlink" title="1.概述"></a>1.概述</h2><p>（1） 将<code>Object</code>对象的一些明显属于语言内部的方法（比如<code>Object.defineProperty</code>），放到<code>Reflect</code>对象上。现阶段，某些方法同时在<code>Object</code>和<code>Reflect</code>对象上部署，未来的新方法将只部署在<code>Reflect</code>对象上。也就是说，从<code>Reflect</code>对象上可以拿到语言内部的方法。</p>
<p>（2） 修改某些<code>Object</code>方法的返回结果，让其变得更合理。比如，<code>Object.defineProperty(obj, name, desc)</code>在无法定义属性时，会抛出一个错误，而<code>Reflect.defineProperty(obj, name, desc)</code>则会返回<code>false</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #6A737D">// 老写法</span></span>
<span class="line"><span style="color: #F97583">try</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  Object.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(target, property, attributes);</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #6A737D">// success</span></span>
<span class="line"><span style="color: #E1E4E8">} </span><span style="color: #F97583">catch</span><span style="color: #E1E4E8"> (e) {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #6A737D">// failure</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (Reflect.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(target, property, attributes)) {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #6A737D">// success</span></span>
<span class="line"><span style="color: #E1E4E8">} </span><span style="color: #F97583">else</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #6A737D">// failure</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div></div></figure>

<p>（3） 让<code>Object</code>操作都变成函数行为。某些<code>Object</code>操作是命令式，比如<code>name in obj</code>和<code>delete obj[name]</code>，而<code>Reflect.has(obj, name)</code>和<code>Reflect.deleteProperty(obj, name)</code>让它们变成了函数行为。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #6A737D">// 老写法</span></span>
<span class="line"><span style="color: #9ECBFF">&#39;assign&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">in</span><span style="color: #E1E4E8"> Object </span><span style="color: #6A737D">// true</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">has</span><span style="color: #E1E4E8">(Object, </span><span style="color: #9ECBFF">&#39;assign&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// true</span></span></code></pre></div></div></figure>

<p>（4）<code>Reflect</code>对象的方法与<code>Proxy</code>对象的方法一一对应，只要是<code>Proxy</code>对象的方法，就能在<code>Reflect</code>对象上找到对应的方法。这就让<code>Proxy</code>对象可以方便地调用对应的<code>Reflect</code>方法，完成默认行为，作为修改行为的基础。也就是说，不管<code>Proxy</code>怎么修改默认行为，你总可以在<code>Reflect</code>上获取默认行为。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #B392F0">Proxy</span><span style="color: #E1E4E8">(target, {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">: </span><span style="color: #F97583">function</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">name</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">value</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">receiver</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">var</span><span style="color: #E1E4E8"> success </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(target, name, value, receiver);</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">if</span><span style="color: #E1E4E8"> (success) {</span></span>
<span class="line"><span style="color: #E1E4E8">      console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;property &#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> name </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39; on &#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> target </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39; set to &#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> value);</span></span>
<span class="line"><span style="color: #E1E4E8">    }</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> success;</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span></code></pre></div></div></figure>

<p>上面代码中，<code>Proxy</code>方法拦截<code>target</code>对象的属性赋值行为。它采用<code>Reflect.set</code>方法将值赋值给对象的属性，确保完成原有的行为，然后再部署额外的功能。</p>
<p>下面是另一个例子。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> loggedObj </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Proxy</span><span style="color: #E1E4E8">(obj, {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">name</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;get&#39;</span><span style="color: #E1E4E8">, target, name);</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(target, name);</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">deleteProperty</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">name</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;delete&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> name);</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">deleteProperty</span><span style="color: #E1E4E8">(target, name);</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">has</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">name</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;has&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> name);</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">has</span><span style="color: #E1E4E8">(target, name);</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span></code></pre></div></div></figure>

<p>上面代码中，每一个<code>Proxy</code>对象的拦截操作（<code>get</code>、<code>delete</code>、<code>has</code>），内部都调用对应的<code>Reflect</code>方法，保证原生行为能够正常执行。添加的工作，就是将每一个操作输出一行日志。</p>
<p>有了<code>Reflect</code>对象以后，很多操作会更易读。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #6A737D">// 老写法</span></span>
<span class="line"><span style="color: #79B8FF">Function</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">.apply.</span><span style="color: #B392F0">call</span><span style="color: #E1E4E8">(Math.floor, </span><span style="color: #79B8FF">undefined</span><span style="color: #E1E4E8">, [</span><span style="color: #79B8FF">1.75</span><span style="color: #E1E4E8">]) </span><span style="color: #6A737D">// 1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">apply</span><span style="color: #E1E4E8">(Math.floor, </span><span style="color: #79B8FF">undefined</span><span style="color: #E1E4E8">, [</span><span style="color: #79B8FF">1.75</span><span style="color: #E1E4E8">]) </span><span style="color: #6A737D">// 1</span></span></code></pre></div></div></figure>

<h2 id="2-静态方法"><a href="#2-静态方法" class="headerlink" title="2.静态方法"></a>2.静态方法</h2><p><code>Reflect</code>对象一共有 13 个静态方法。</p>
<ul>
<li>Reflect.apply(target, thisArg, args)</li>
<li>Reflect.construct(target, args)</li>
<li>Reflect.get(target, name, receiver)</li>
<li>Reflect.set(target, name, value, receiver)</li>
<li>Reflect.defineProperty(target, name, desc)</li>
<li>Reflect.deleteProperty(target, name)</li>
<li>Reflect.has(target, name)</li>
<li>Reflect.ownKeys(target)</li>
<li>Reflect.isExtensible(target)</li>
<li>Reflect.preventExtensions(target)</li>
<li>Reflect.getOwnPropertyDescriptor(target, name)</li>
<li>Reflect.getPrototypeOf(target)</li>
<li>Reflect.setPrototypeOf(target, prototype)</li>
</ul>
<p>上面这些方法的作用，大部分与<code>Object</code>对象的同名方法的作用都是相同的，而且它与<code>Proxy</code>对象的方法是一一对应的。下面是对它们的解释。</p>
<h3 id="Reflect-get-target-name-receiver"><a href="#Reflect-get-target-name-receiver" class="headerlink" title="Reflect.get(target, name, receiver)"></a>Reflect.get(target, name, receiver)</h3><p><code>Reflect.get</code>方法查找并返回<code>target</code>对象的<code>name</code>属性，如果没有该属性，则返回<code>undefined</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  bar: </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #F97583">get</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">baz</span><span style="color: #E1E4E8">() {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.foo </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.bar;</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 1</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;bar&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 2</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;baz&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 3</span></span></code></pre></div></div></figure>

<p>如果<code>name</code>属性部署了读取函数（getter），则读取函数的<code>this</code>绑定<code>receiver</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  bar: </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #F97583">get</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">baz</span><span style="color: #E1E4E8">() {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.foo </span><span style="color: #F97583">+</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.bar;</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myReceiverObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">4</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  bar: </span><span style="color: #79B8FF">4</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;baz&#39;</span><span style="color: #E1E4E8">, myReceiverObject) </span><span style="color: #6A737D">// 8</span></span></code></pre></div></div></figure>

<p>如果第一个参数不是对象，<code>Reflect.get</code>方法会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 报错</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">get</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">false</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 报错</span></span></code></pre></div></div></figure>

<h3 id="Reflect-set-target-name-value-receiver"><a href="#Reflect-set-target-name-value-receiver" class="headerlink" title="Reflect.set(target, name, value, receiver)"></a>Reflect.set(target, name, value, receiver)</h3><p><code>Reflect.set</code>方法设置<code>target</code>对象的<code>name</code>属性等于<code>value</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #F97583">set</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">bar</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">value</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.foo </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> value;</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">myObject.foo </span><span style="color: #6A737D">// 1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8">);</span></span>
<span class="line"><span style="color: #E1E4E8">myObject.foo </span><span style="color: #6A737D">// 2</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;bar&#39;</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">3</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">myObject.foo </span><span style="color: #6A737D">// 3</span></span></code></pre></div></div></figure>

<p>如果<code>name</code>属性设置了赋值函数，则赋值函数的<code>this</code>绑定<code>receiver</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">4</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #F97583">set</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">bar</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">value</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.foo </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> value;</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myReceiverObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">0</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;bar&#39;</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">, myReceiverObject);</span></span>
<span class="line"><span style="color: #E1E4E8">myObject.foo </span><span style="color: #6A737D">// 4</span></span>
<span class="line"><span style="color: #E1E4E8">myReceiverObject.foo </span><span style="color: #6A737D">// 1</span></span></code></pre></div></div></figure>

<p>注意，如果 <code>Proxy</code>对象和 <code>Reflect</code>对象联合使用，前者拦截赋值操作，后者完成赋值的默认行为，而且传入了<code>receiver</code>，那么<code>Reflect.set</code>会触发<code>Proxy.defineProperty</code>拦截。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">let</span><span style="color: #E1E4E8"> p </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  a: </span><span style="color: #9ECBFF">&#39;a&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">let</span><span style="color: #E1E4E8"> handler </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">key</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">value</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">receiver</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;set&#39;</span><span style="color: #E1E4E8">);</span></span>
<span class="line"><span style="color: #E1E4E8">    Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(target, key, value, receiver)</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">key</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">attribute</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;defineProperty&#39;</span><span style="color: #E1E4E8">);</span></span>
<span class="line"><span style="color: #E1E4E8">    Reflect.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(target, key, attribute);</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">let</span><span style="color: #E1E4E8"> obj </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Proxy</span><span style="color: #E1E4E8">(p, handler);</span></span>
<span class="line"><span style="color: #E1E4E8">obj.a </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;A&#39;</span><span style="color: #E1E4E8">;</span></span>
<span class="line"><span style="color: #6A737D">// set</span></span>
<span class="line"><span style="color: #6A737D">// defineProperty</span></span></code></pre></div></div></figure>

<p>上面代码中，<code>Proxy.set</code>拦截里面使用了<code>Reflect.set</code>，而且传入了<code>receiver</code>，导致触发<code>Proxy.defineProperty</code>拦截。这是因为<code>Proxy.set</code>的<code>receiver</code>参数总是指向当前的 <code>Proxy</code>实例（即上例的<code>obj</code>），而<code>Reflect.set</code>一旦传入<code>receiver</code>，就会将属性赋值到<code>receiver</code>上面（即<code>obj</code>），导致触发<code>defineProperty</code>拦截。如果<code>Reflect.set</code>没有传入<code>receiver</code>，那么就不会触发<code>defineProperty</code>拦截。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">let</span><span style="color: #E1E4E8"> p </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  a: </span><span style="color: #9ECBFF">&#39;a&#39;</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">let</span><span style="color: #E1E4E8"> handler </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">key</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">value</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">receiver</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;set&#39;</span><span style="color: #E1E4E8">);</span></span>
<span class="line"><span style="color: #E1E4E8">    Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(target, key, value)</span></span>
<span class="line"><span style="color: #E1E4E8">  },</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">key</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">attribute</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;defineProperty&#39;</span><span style="color: #E1E4E8">);</span></span>
<span class="line"><span style="color: #E1E4E8">    Reflect.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(target, key, attribute);</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">let</span><span style="color: #E1E4E8"> obj </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Proxy</span><span style="color: #E1E4E8">(p, handler);</span></span>
<span class="line"><span style="color: #E1E4E8">obj.a </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;A&#39;</span><span style="color: #E1E4E8">;</span></span>
<span class="line"><span style="color: #6A737D">// set</span></span></code></pre></div></div></figure>

<p>如果第一个参数不是对象，<code>Reflect.set</code>会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">, {}) </span><span style="color: #6A737D">// 报错</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">false</span><span style="color: #E1E4E8">, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">, {}) </span><span style="color: #6A737D">// 报错</span></span></code></pre></div></div></figure>

<h3 id="Reflect-has-obj-name"><a href="#Reflect-has-obj-name" class="headerlink" title="Reflect.has(obj, name)"></a>Reflect.has(obj, name)</h3><p><code>Reflect.has</code>方法对应<code>name in obj</code>里面的<code>in</code>运算符。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">in</span><span style="color: #E1E4E8"> myObject </span><span style="color: #6A737D">// true</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">has</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// true</span></span></code></pre></div></div></figure>

<p>如果<code>Reflect.has()</code>方法的第一个参数不是对象，会报错。</p>
<h3 id="Reflect-deleteProperty-obj-name"><a href="#Reflect-deleteProperty-obj-name" class="headerlink" title="Reflect.deleteProperty(obj, name)"></a>Reflect.deleteProperty(obj, name)</h3><p><code>Reflect.deleteProperty</code>方法等同于<code>delete obj[name]</code>，用于删除对象的属性。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">myObj</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> { foo: </span><span style="color: #9ECBFF">&#39;bar&#39;</span><span style="color: #E1E4E8"> };</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #F97583">delete</span><span style="color: #E1E4E8"> myObj.foo;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">deleteProperty</span><span style="color: #E1E4E8">(myObj, </span><span style="color: #9ECBFF">&#39;foo&#39;</span><span style="color: #E1E4E8">);</span></span></code></pre></div></div></figure>

<p>该方法返回一个布尔值。如果删除成功，或者被删除的属性不存在，返回<code>true</code>；删除失败，被删除的属性依然存在，返回<code>false</code>。</p>
<p>如果<code>Reflect.deleteProperty()</code>方法的第一个参数不是对象，会报错。</p>
<h3 id="Reflect-construct-target-args"><a href="#Reflect-construct-target-args" class="headerlink" title="Reflect.construct(target, args)"></a>Reflect.construct(target, args)</h3><p><code>Reflect.construct</code>方法等同于<code>new target(...args)</code>，这提供了一种不使用<code>new</code>，来调用构造函数的方法。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">function</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Greeting</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">name</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #79B8FF">this</span><span style="color: #E1E4E8">.name </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> name;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// new 的写法</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">instance</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Greeting</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;张三&#39;</span><span style="color: #E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// Reflect.construct 的写法</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">instance</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">construct</span><span style="color: #E1E4E8">(Greeting, [</span><span style="color: #9ECBFF">&#39;张三&#39;</span><span style="color: #E1E4E8">]);</span></span></code></pre></div></div></figure>

<p>如果<code>Reflect.construct()</code>方法的第一个参数不是函数，会报错。</p>
<h3 id="Reflect-getPrototypeOf-obj"><a href="#Reflect-getPrototypeOf-obj" class="headerlink" title="Reflect.getPrototypeOf(obj)"></a>Reflect.getPrototypeOf(obj)</h3><p><code>Reflect.getPrototypeOf</code>方法用于读取对象的<code>__proto__</code>属性，对应<code>Object.getPrototypeOf(obj)</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">myObj</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">FancyThing</span><span style="color: #E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">getPrototypeOf</span><span style="color: #E1E4E8">(myObj) </span><span style="color: #F97583">===</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">FancyThing</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">getPrototypeOf</span><span style="color: #E1E4E8">(myObj) </span><span style="color: #F97583">===</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">FancyThing</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">;</span></span></code></pre></div></div></figure>

<p><code>Reflect.getPrototypeOf</code>和<code>Object.getPrototypeOf</code>的一个区别是，如果参数不是对象，<code>Object.getPrototypeOf</code>会将这个参数转为对象，然后再运行，而<code>Reflect.getPrototypeOf</code>会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">getPrototypeOf</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// Number {[[PrimitiveValue]]: 0}</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">getPrototypeOf</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 报错</span></span></code></pre></div></div></figure>

<h3 id="Reflect-setPrototypeOf-obj-newProto"><a href="#Reflect-setPrototypeOf-obj-newProto" class="headerlink" title="Reflect.setPrototypeOf(obj, newProto)"></a>Reflect.setPrototypeOf(obj, newProto)</h3><p><code>Reflect.setPrototypeOf</code>方法用于设置目标对象的原型（prototype），对应<code>Object.setPrototypeOf(obj, newProto)</code>方法。它返回一个布尔值，表示是否设置成功。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">myObj</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(myObj, </span><span style="color: #79B8FF">Array</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(myObj, </span><span style="color: #79B8FF">Array</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">myObj.</span><span style="color: #79B8FF">length</span><span style="color: #E1E4E8"> </span><span style="color: #6A737D">// 0</span></span></code></pre></div></div></figure>

<p>如果无法设置目标对象的原型（比如，目标对象禁止扩展），<code>Reflect.setPrototypeOf</code>方法返回<code>false</code>。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">({}, </span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #6A737D">// true</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(Object.</span><span style="color: #B392F0">freeze</span><span style="color: #E1E4E8">({}), </span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #6A737D">// false</span></span></code></pre></div></div></figure>

<p>如果第一个参数不是对象，<code>Object.setPrototypeOf</code>会返回第一个参数本身，而<code>Reflect.setPrototypeOf</code>会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">, {})</span></span>
<span class="line"><span style="color: #6A737D">// 1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">, {})</span></span>
<span class="line"><span style="color: #6A737D">// TypeError: Reflect.setPrototypeOf called on non-object</span></span></code></pre></div></div></figure>

<p>如果第一个参数是<code>undefined</code>或<code>null</code>，<code>Object.setPrototypeOf</code>和<code>Reflect.setPrototypeOf</code>都会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">, {})</span></span>
<span class="line"><span style="color: #6A737D">// TypeError: Object.setPrototypeOf called on null or undefined</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">setPrototypeOf</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">null</span><span style="color: #E1E4E8">, {})</span></span>
<span class="line"><span style="color: #6A737D">// TypeError: Reflect.setPrototypeOf called on non-object</span></span></code></pre></div></div></figure>

<h3 id="Reflect-apply-func-thisArg-args"><a href="#Reflect-apply-func-thisArg-args" class="headerlink" title="Reflect.apply(func, thisArg, args)"></a>Reflect.apply(func, thisArg, args)</h3><p><code>Reflect.apply</code>方法等同于<code>Function.prototype.apply.call(func, thisArg, args)</code>，用于绑定<code>this</code>对象后执行给定函数。</p>
<p>一般来说，如果要绑定一个函数的<code>this</code>对象，可以这样写<code>fn.apply(obj, args)</code>，但是如果函数定义了自己的<code>apply</code>方法，就只能写成<code>Function.prototype.apply.call(fn, obj, args)</code>，采用<code>Reflect</code>对象可以简化这种操作。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">ages</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> [</span><span style="color: #79B8FF">11</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">33</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">12</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">54</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">18</span><span style="color: #E1E4E8">, </span><span style="color: #79B8FF">96</span><span style="color: #E1E4E8">];</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">youngest</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Math.min.</span><span style="color: #B392F0">apply</span><span style="color: #E1E4E8">(Math, ages);</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">oldest</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Math.max.</span><span style="color: #B392F0">apply</span><span style="color: #E1E4E8">(Math, ages);</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">type</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">Object</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">.toString.</span><span style="color: #B392F0">call</span><span style="color: #E1E4E8">(youngest);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">youngest</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">apply</span><span style="color: #E1E4E8">(Math.min, Math, ages);</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">oldest</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">apply</span><span style="color: #E1E4E8">(Math.max, Math, ages);</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">type</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">apply</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">Object</span><span style="color: #E1E4E8">.</span><span style="color: #79B8FF">prototype</span><span style="color: #E1E4E8">.toString, youngest, []);</span></span></code></pre></div></div></figure>

<h3 id="Reflect-defineProperty-target-propertyKey-attributes"><a href="#Reflect-defineProperty-target-propertyKey-attributes" class="headerlink" title="Reflect.defineProperty(target, propertyKey, attributes)"></a>Reflect.defineProperty(target, propertyKey, attributes)</h3><p><code>Reflect.defineProperty</code>方法基本等同于<code>Object.defineProperty</code>，用来为对象定义属性。未来，后者会被逐渐废除，请从现在开始就使用<code>Reflect.defineProperty</code>代替它。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">function</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">MyDate</span><span style="color: #E1E4E8">() {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #6A737D">/*…*/</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(MyDate, </span><span style="color: #9ECBFF">&#39;now&#39;</span><span style="color: #E1E4E8">, {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">value</span><span style="color: #E1E4E8">: () </span><span style="color: #F97583">=&gt;</span><span style="color: #E1E4E8"> Date.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(MyDate, </span><span style="color: #9ECBFF">&#39;now&#39;</span><span style="color: #E1E4E8">, {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">value</span><span style="color: #E1E4E8">: () </span><span style="color: #F97583">=&gt;</span><span style="color: #E1E4E8"> Date.</span><span style="color: #B392F0">now</span><span style="color: #E1E4E8">()</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span></code></pre></div></div></figure>

<p>如果<code>Reflect.defineProperty</code>的第一个参数不是对象，就会抛出错误，比如<code>Reflect.defineProperty(1, &#39;foo&#39;)</code>。</p>
<p>这个方法可以与<code>Proxy.defineProperty</code>配合使用。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">p</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Proxy</span><span style="color: #E1E4E8">({}, {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">prop</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">descriptor</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">    console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(descriptor);</span></span>
<span class="line"><span style="color: #E1E4E8">    </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(target, prop, descriptor);</span></span>
<span class="line"><span style="color: #E1E4E8">  }</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">p.foo </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;bar&#39;</span><span style="color: #E1E4E8">;</span></span>
<span class="line"><span style="color: #6A737D">// {value: &quot;bar&quot;, writable: true, enumerable: true, configurable: true}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">p.foo </span><span style="color: #6A737D">// &quot;bar&quot;</span></span></code></pre></div></div></figure>

<p>上面代码中，<code>Proxy.defineProperty</code>对属性赋值设置了拦截，然后使用<code>Reflect.defineProperty</code>完成了赋值。</p>
<h3 id="Reflect-getOwnPropertyDescriptor-target-propertyKey"><a href="#Reflect-getOwnPropertyDescriptor-target-propertyKey" class="headerlink" title="Reflect.getOwnPropertyDescriptor(target, propertyKey)"></a>Reflect.getOwnPropertyDescriptor(target, propertyKey)</h3><p><code>Reflect.getOwnPropertyDescriptor</code>基本等同于<code>Object.getOwnPropertyDescriptor</code>，用于得到指定属性的描述对象，将来会替代掉后者。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {};</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">defineProperty</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;hidden&#39;</span><span style="color: #E1E4E8">, {</span></span>
<span class="line"><span style="color: #E1E4E8">  value: </span><span style="color: #79B8FF">true</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  enumerable: </span><span style="color: #79B8FF">false</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> theDescriptor </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Object.</span><span style="color: #B392F0">getOwnPropertyDescriptor</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;hidden&#39;</span><span style="color: #E1E4E8">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> theDescriptor </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">getOwnPropertyDescriptor</span><span style="color: #E1E4E8">(myObject, </span><span style="color: #9ECBFF">&#39;hidden&#39;</span><span style="color: #E1E4E8">);</span></span></code></pre></div></div></figure>

<p><code>Reflect.getOwnPropertyDescriptor</code>和<code>Object.getOwnPropertyDescriptor</code>的一个区别是，如果第一个参数不是对象，<code>Object.getOwnPropertyDescriptor(1, &#39;foo&#39;)</code>不报错，返回<code>undefined</code>，而<code>Reflect.getOwnPropertyDescriptor(1, &#39;foo&#39;)</code>会抛出错误，表示参数非法。</p>
<h3 id="Reflect-isExtensible-target"><a href="#Reflect-isExtensible-target" class="headerlink" title="Reflect.isExtensible (target)"></a>Reflect.isExtensible (target)</h3><p><code>Reflect.isExtensible</code>方法对应<code>Object.isExtensible</code>，返回一个布尔值，表示当前对象是否可扩展。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">myObject</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">isExtensible</span><span style="color: #E1E4E8">(myObject) </span><span style="color: #6A737D">// true</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">isExtensible</span><span style="color: #E1E4E8">(myObject) </span><span style="color: #6A737D">// true</span></span></code></pre></div></div></figure>

<p>如果参数不是对象，<code>Object.isExtensible</code>会返回<code>false</code>，因为非对象本来就是不可扩展的，而<code>Reflect.isExtensible</code>会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">isExtensible</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// false</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">isExtensible</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 报错</span></span></code></pre></div></div></figure>

<h3 id="Reflect-preventExtensions-target"><a href="#Reflect-preventExtensions-target" class="headerlink" title="Reflect.preventExtensions(target)"></a>Reflect.preventExtensions(target)</h3><p><code>Reflect.preventExtensions</code>对应<code>Object.preventExtensions</code>方法，用于让一个对象变为不可扩展。它返回一个布尔值，表示是否操作成功。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">preventExtensions</span><span style="color: #E1E4E8">(myObject) </span><span style="color: #6A737D">// Object {}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">preventExtensions</span><span style="color: #E1E4E8">(myObject) </span><span style="color: #6A737D">// true</span></span></code></pre></div></div></figure>

<p>如果参数不是对象，<code>Object.preventExtensions</code>在 ES5 环境报错，在 ES6 环境返回传入的参数，而<code>Reflect.preventExtensions</code>会报错。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #6A737D">// ES5 环境</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">preventExtensions</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 报错</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// ES6 环境</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">preventExtensions</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">preventExtensions</span><span style="color: #E1E4E8">(</span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">) </span><span style="color: #6A737D">// 报错</span></span></code></pre></div></div></figure>

<h3 id="Reflect-ownKeys-target"><a href="#Reflect-ownKeys-target" class="headerlink" title="Reflect.ownKeys (target)"></a>Reflect.ownKeys (target)</h3><p><code>Reflect.ownKeys</code>方法用于返回对象的所有属性，基本等同于<code>Object.getOwnPropertyNames</code>与<code>Object.getOwnPropertySymbols</code>之和。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">var</span><span style="color: #E1E4E8"> myObject </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> {</span></span>
<span class="line"><span style="color: #E1E4E8">  foo: </span><span style="color: #79B8FF">1</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  bar: </span><span style="color: #79B8FF">2</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  [Symbol.</span><span style="color: #B392F0">for</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;baz&#39;</span><span style="color: #E1E4E8">)]: </span><span style="color: #79B8FF">3</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  [Symbol.</span><span style="color: #B392F0">for</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">&#39;bing&#39;</span><span style="color: #E1E4E8">)]: </span><span style="color: #79B8FF">4</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 旧写法</span></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">getOwnPropertyNames</span><span style="color: #E1E4E8">(myObject)</span></span>
<span class="line"><span style="color: #6A737D">// [&#39;foo&#39;, &#39;bar&#39;]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #E1E4E8">Object.</span><span style="color: #B392F0">getOwnPropertySymbols</span><span style="color: #E1E4E8">(myObject)</span></span>
<span class="line"><span style="color: #6A737D">//[Symbol(baz), Symbol(bing)]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// 新写法</span></span>
<span class="line"><span style="color: #E1E4E8">Reflect.</span><span style="color: #B392F0">ownKeys</span><span style="color: #E1E4E8">(myObject)</span></span>
<span class="line"><span style="color: #6A737D">// [&#39;foo&#39;, &#39;bar&#39;, Symbol(baz), Symbol(bing)]</span></span></code></pre></div></div></figure>

<p>如果<code>Reflect.ownKeys()</code>方法的第一个参数不是对象，会报错。</p>
<h2 id="实例：使用-Proxy-实现观察者模式"><a href="#实例：使用-Proxy-实现观察者模式" class="headerlink" title="实例：使用 Proxy 实现观察者模式"></a>实例：使用 Proxy 实现观察者模式</h2><p>观察者模式（Observer mode）指的是函数自动观察数据对象，一旦对象有变化，函数就会自动执行。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">person</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">observable</span><span style="color: #E1E4E8">({</span></span>
<span class="line"><span style="color: #E1E4E8">  name: </span><span style="color: #9ECBFF">&#39;张三&#39;</span><span style="color: #E1E4E8">,</span></span>
<span class="line"><span style="color: #E1E4E8">  age: </span><span style="color: #79B8FF">20</span></span>
<span class="line"><span style="color: #E1E4E8">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">function</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">print</span><span style="color: #E1E4E8">() {</span></span>
<span class="line"><span style="color: #E1E4E8">  console.</span><span style="color: #B392F0">log</span><span style="color: #E1E4E8">(</span><span style="color: #9ECBFF">`${</span><span style="color: #E1E4E8">person</span><span style="color: #9ECBFF">.</span><span style="color: #E1E4E8">name</span><span style="color: #9ECBFF">}, ${</span><span style="color: #E1E4E8">person</span><span style="color: #9ECBFF">.</span><span style="color: #E1E4E8">age</span><span style="color: #9ECBFF">}`</span><span style="color: #E1E4E8">)</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #B392F0">observe</span><span style="color: #E1E4E8">(print);</span></span>
<span class="line"><span style="color: #E1E4E8">person.name </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #9ECBFF">&#39;李四&#39;</span><span style="color: #E1E4E8">;</span></span>
<span class="line"><span style="color: #6A737D">// 输出</span></span>
<span class="line"><span style="color: #6A737D">// 李四, 20</span></span></code></pre></div></div></figure>

<p>上面代码中，数据对象<code>person</code>是观察目标，函数<code>print</code>是观察者。一旦数据对象发生变化，<code>print</code>就会自动执行。</p>
<p>下面，使用 Proxy 写一个观察者模式的最简单实现，即实现<code>observable</code>和<code>observe</code>这两个函数。思路是<code>observable</code>函数返回一个原始对象的 Proxy 代理，拦截赋值操作，触发充当观察者的各个函数。</p>
<figure class="shiki javascript"><div class='codeblock'><div class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div><div class="code"><pre class="shiki github-dark"><code><span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">queuedObservers</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Set</span><span style="color: #E1E4E8">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">observe</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #FFAB70">fn</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=&gt;</span><span style="color: #E1E4E8"> queuedObservers.</span><span style="color: #B392F0">add</span><span style="color: #E1E4E8">(fn);</span></span>
<span class="line"><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">observable</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> </span><span style="color: #FFAB70">obj</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=&gt;</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">new</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">Proxy</span><span style="color: #E1E4E8">(obj, {set});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F97583">function</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">target</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">key</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">value</span><span style="color: #E1E4E8">, </span><span style="color: #FFAB70">receiver</span><span style="color: #E1E4E8">) {</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #F97583">const</span><span style="color: #E1E4E8"> </span><span style="color: #79B8FF">result</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=</span><span style="color: #E1E4E8"> Reflect.</span><span style="color: #B392F0">set</span><span style="color: #E1E4E8">(target, key, value, receiver);</span></span>
<span class="line"><span style="color: #E1E4E8">  queuedObservers.</span><span style="color: #B392F0">forEach</span><span style="color: #E1E4E8">(</span><span style="color: #FFAB70">observer</span><span style="color: #E1E4E8"> </span><span style="color: #F97583">=&gt;</span><span style="color: #E1E4E8"> </span><span style="color: #B392F0">observer</span><span style="color: #E1E4E8">());</span></span>
<span class="line"><span style="color: #E1E4E8">  </span><span style="color: #F97583">return</span><span style="color: #E1E4E8"> result;</span></span>
<span class="line"><span style="color: #E1E4E8">}</span></span></code></pre></div></div></figure>

<p>上面代码中，先定义了一个<code>Set</code>集合，所有观察者函数都放进这个集合。然后，<code>observable</code>函数返回原始对象的代理，拦截赋值操作。拦截函数<code>set</code>之中，会自动执行所有观察者。</p>

    
  </article>

  
      
    <div class="nexmoe-post-copyright">
        <strong>本文作者：</strong>阮一峰<br>
        
            <strong>文章来源：</strong><a href="https://es6.ruanyifeng.com/#docs/reflect" title="https:&#x2F;&#x2F;es6.ruanyifeng.com&#x2F;#docs&#x2F;reflect" target="_blank" rel="noopener">https:&#x2F;&#x2F;es6.ruanyifeng.com&#x2F;#docs&#x2F;reflect</a><br>
        
        <strong>本文链接：</strong><a href="https://www.tangyuxian.com/2021/06/10/%E5%89%8D%E7%AB%AF/es6/es6-Reflect%E7%9B%B8%E5%85%B3/" title="https:&#x2F;&#x2F;www.tangyuxian.com&#x2F;2021&#x2F;06&#x2F;10&#x2F;%E5%89%8D%E7%AB%AF&#x2F;es6&#x2F;es6-Reflect%E7%9B%B8%E5%85%B3&#x2F;" target="_blank" rel="noopener">https:&#x2F;&#x2F;www.tangyuxian.com&#x2F;2021&#x2F;06&#x2F;10&#x2F;%E5%89%8D%E7%AB%AF&#x2F;es6&#x2F;es6-Reflect%E7%9B%B8%E5%85%B3&#x2F;</a><br>

        
            <strong>版权声明：</strong>本文采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/cn/deed.zh" target="_blank">CC BY-NC-SA 3.0 CN</a> 协议进行许可

        
    </div>


  
  
  <div class="nexmoe-post-meta nexmoe-rainbow">
   
    
        <a class="nexmoefont icon-tag-fill -none-link" href="/tags/es6/" rel="tag">es6</a> <a class="nexmoefont icon-tag-fill -none-link" href="/tags/%E8%BD%AC%E8%BD%BD/" rel="tag">转载</a>
    
</div>
  
  
    <script async src="/js/copy-codeblock.js?v=1763992123959"></script>
  

  
      <div class="nexmoe-post-footer">
          <div class="valine"></div>
<script src='https://lib.baomitu.com/valine/1.3.9/Valine.min.js'></script>
<script>
  new Valine({
      el: '.valine',
      appId: 'r5zxC0st0DDjPA9auXzMV7HY-gzGzoHsz',
      appKey: '3bqCsovpyfTPHUzTHovd3V3V'
  })
</script>

      </div>
  
</div></div><div class="nexmoe-post-right">    <div class="nexmoe-fixed">
        <div class="nexmoe-tool">

            

            
            
            <button class="mdui-fab catalog" style="overflow:unset;">
                <i class="nexmoefont icon-i-catalog"></i>
                <div class="nexmoe-toc">
                    <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E6%A6%82%E8%BF%B0"><span class="toc-number">1.</span> <span class="toc-text">1.概述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95"><span class="toc-number">2.</span> <span class="toc-text">2.静态方法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-get-target-name-receiver"><span class="toc-number">2.1.</span> <span class="toc-text">Reflect.get(target, name, receiver)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-set-target-name-value-receiver"><span class="toc-number">2.2.</span> <span class="toc-text">Reflect.set(target, name, value, receiver)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-has-obj-name"><span class="toc-number">2.3.</span> <span class="toc-text">Reflect.has(obj, name)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-deleteProperty-obj-name"><span class="toc-number">2.4.</span> <span class="toc-text">Reflect.deleteProperty(obj, name)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-construct-target-args"><span class="toc-number">2.5.</span> <span class="toc-text">Reflect.construct(target, args)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-getPrototypeOf-obj"><span class="toc-number">2.6.</span> <span class="toc-text">Reflect.getPrototypeOf(obj)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-setPrototypeOf-obj-newProto"><span class="toc-number">2.7.</span> <span class="toc-text">Reflect.setPrototypeOf(obj, newProto)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-apply-func-thisArg-args"><span class="toc-number">2.8.</span> <span class="toc-text">Reflect.apply(func, thisArg, args)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-defineProperty-target-propertyKey-attributes"><span class="toc-number">2.9.</span> <span class="toc-text">Reflect.defineProperty(target, propertyKey, attributes)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-getOwnPropertyDescriptor-target-propertyKey"><span class="toc-number">2.10.</span> <span class="toc-text">Reflect.getOwnPropertyDescriptor(target, propertyKey)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-isExtensible-target"><span class="toc-number">2.11.</span> <span class="toc-text">Reflect.isExtensible (target)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-preventExtensions-target"><span class="toc-number">2.12.</span> <span class="toc-text">Reflect.preventExtensions(target)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Reflect-ownKeys-target"><span class="toc-number">2.13.</span> <span class="toc-text">Reflect.ownKeys (target)</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%9E%E4%BE%8B%EF%BC%9A%E4%BD%BF%E7%94%A8-Proxy-%E5%AE%9E%E7%8E%B0%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F"><span class="toc-number">3.</span> <span class="toc-text">实例：使用 Proxy 实现观察者模式</span></a></li></ol>
                </div>
            </button>
            

            

            <a href="#nexmoe-content" class="backtop toc-link" aria-label="Back To Top" title="top"><button class="mdui-fab mdui-ripple"><i class="nexmoefont icon-caret-top"></i></button></a>
        </div>
    </div>
</div></div><div id="nexmoe-pendant"><div class="nexmoe-drawer mdui-drawer nexmoe-pd" id="drawer">
    
        
            <div class="nexmoe-pd-item">
                <div class="clock">
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="memory"></div>
        <div class="needle" id="hours"></div>
        <div class="needle" id="minutes"></div>
        <div class="needle" id="seconds"></div>
        <div class="clock_logo">

        </div>

    </div>
<script>
        // ----- Variable declaration

        var data = {
                dt: new Date(),
                hours: {
                        el: document.querySelector('#hours'),
                        val: 0 },

                minutes: {
                        el: document.querySelector('#minutes'),
                        val: 0 },

                seconds: {
                        el: document.querySelector('#seconds'),
                        val: 0 },

                renderTime: 1000 };


        // ----- Clock rendering logic

        updateTime = () => {
                let hour = data.dt.getHours();
                let minute = data.dt.getMinutes();
                let second = data.dt.getSeconds();

                data.hours.el.classList.add('moving');
                data.minutes.el.classList.add('moving');
                data.seconds.el.classList.add('moving');

                data.hours.val = hour == 0 && data.hours.val == 59 * 6 * 5 ? 360 : hour * 6 * 5;
                data.minutes.val = minute == 0 && data.minutes.val == 59 * 6 ? 360 : minute * 6;
                data.seconds.val = second == 0 && data.seconds.val == 59 * 6 ? 360 : second * 6;

                data.hours.el.style.transform = `translate(-50%, -75%) rotate(${data.hours.val}deg)`;
                data.minutes.el.style.transform = `translate(-50%, -75%) rotate(${data.minutes.val}deg)`;
                data.seconds.el.style.transform = `translate(-50%, -75%) rotate(${data.seconds.val}deg)`;

                data.dt.setSeconds(second + 1);
        };

        // ----- Clock execution

        setInterval(() => {
                updateTime();
        }, data.renderTime);

        updateTime();

        // ----- Events area

        data.seconds.el.addEventListener('transitionend', () => {
                data.hours.el.classList.remove('moving');
                data.minutes.el.classList.remove('moving');
                data.seconds.el.classList.remove('moving');

                // if (data.hours.val == 360) {
                //   data.hours.el.style.transform = 'translate(-50%, -75%) rotate(0deg)';
                // }

                if (data.minutes.val == 360) {
                        data.minutes.el.style.transform = 'translate(-50%, -75%) rotate(0deg)';
                }

                if (data.seconds.val == 360) {
                        data.seconds.el.style.transform = 'translate(-50%, -75%) rotate(0deg)';
                }
        });

</script>
<style>
    .clock {
        background-color: #ffffff;
        width: 70vw;
        height: 70vw;
        max-width: 70vh;
        max-height: 70vh;
        border: solid 2.8vw var(--color-primary);
        position: relative;
        overflow: hidden;
        border-radius: 50%;
        box-sizing: border-box;
        box-shadow: 0 1.4vw 2.8vw var(--color2);
        zoom:0.2
    }

    .memory {
        position: absolute;
        top: 50%;
        left: 50%;
        transform-origin: center;
    }

    .memory:nth-child(1) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(0deg) translateY(-520%);
    }

    .memory:nth-child(2) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(6deg) translateY(-1461%);
    }

    .memory:nth-child(3) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(12deg) translateY(-1461%);
    }

    .memory:nth-child(4) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(18deg) translateY(-1461%);
    }

    .memory:nth-child(5) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(24deg) translateY(-1461%);
    }

    .memory:nth-child(6) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(30deg) translateY(-520%);
    }

    .memory:nth-child(7) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(36deg) translateY(-1461%);
    }

    .memory:nth-child(8) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(42deg) translateY(-1461%);
    }

    .memory:nth-child(9) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(48deg) translateY(-1461%);
    }

    .memory:nth-child(10) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(54deg) translateY(-1461%);
    }

    .memory:nth-child(11) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(60deg) translateY(-520%);
    }

    .memory:nth-child(12) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(66deg) translateY(-1461%);
    }

    .memory:nth-child(13) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(72deg) translateY(-1461%);
    }

    .memory:nth-child(14) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(78deg) translateY(-1461%);
    }

    .memory:nth-child(15) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(84deg) translateY(-1461%);
    }

    .memory:nth-child(16) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(90deg) translateY(-520%);
    }

    .memory:nth-child(17) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(96deg) translateY(-1461%);
    }

    .memory:nth-child(18) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(102deg) translateY(-1461%);
    }

    .memory:nth-child(19) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(108deg) translateY(-1461%);
    }

    .memory:nth-child(20) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(114deg) translateY(-1461%);
    }

    .memory:nth-child(21) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(120deg) translateY(-520%);
    }

    .memory:nth-child(22) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(126deg) translateY(-1461%);
    }

    .memory:nth-child(23) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(132deg) translateY(-1461%);
    }

    .memory:nth-child(24) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(138deg) translateY(-1461%);
    }

    .memory:nth-child(25) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(144deg) translateY(-1461%);
    }

    .memory:nth-child(26) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(150deg) translateY(-520%);
    }

    .memory:nth-child(27) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(156deg) translateY(-1461%);
    }

    .memory:nth-child(28) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(162deg) translateY(-1461%);
    }

    .memory:nth-child(29) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(168deg) translateY(-1461%);
    }

    .memory:nth-child(30) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(174deg) translateY(-1461%);
    }

    .memory:nth-child(31) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(180deg) translateY(-520%);
    }

    .memory:nth-child(32) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(186deg) translateY(-1461%);
    }

    .memory:nth-child(33) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(192deg) translateY(-1461%);
    }

    .memory:nth-child(34) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(198deg) translateY(-1461%);
    }

    .memory:nth-child(35) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(204deg) translateY(-1461%);
    }

    .memory:nth-child(36) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(210deg) translateY(-520%);
    }

    .memory:nth-child(37) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(216deg) translateY(-1461%);
    }

    .memory:nth-child(38) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(222deg) translateY(-1461%);
    }

    .memory:nth-child(39) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(228deg) translateY(-1461%);
    }

    .memory:nth-child(40) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(234deg) translateY(-1461%);
    }

    .memory:nth-child(41) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(240deg) translateY(-520%);
    }

    .memory:nth-child(42) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(246deg) translateY(-1461%);
    }

    .memory:nth-child(43) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(252deg) translateY(-1461%);
    }

    .memory:nth-child(44) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(258deg) translateY(-1461%);
    }

    .memory:nth-child(45) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(264deg) translateY(-1461%);
    }

    .memory:nth-child(46) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(270deg) translateY(-520%);
    }

    .memory:nth-child(47) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(276deg) translateY(-1461%);
    }

    .memory:nth-child(48) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(282deg) translateY(-1461%);
    }

    .memory:nth-child(49) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(288deg) translateY(-1461%);
    }

    .memory:nth-child(50) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(294deg) translateY(-1461%);
    }

    .memory:nth-child(51) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(300deg) translateY(-520%);
    }

    .memory:nth-child(52) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(306deg) translateY(-1461%);
    }

    .memory:nth-child(53) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(312deg) translateY(-1461%);
    }

    .memory:nth-child(54) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(318deg) translateY(-1461%);
    }

    .memory:nth-child(55) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(324deg) translateY(-1461%);
    }

    .memory:nth-child(56) {
        background-color: var(--color-primary);
        width: 2%;
        height: 8%;
        transform: translate(-50%, -50%) rotate(330deg) translateY(-520%);
    }

    .memory:nth-child(57) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(336deg) translateY(-1461%);
    }

    .memory:nth-child(58) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(342deg) translateY(-1461%);
    }

    .memory:nth-child(59) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(348deg) translateY(-1461%);
    }

    .memory:nth-child(60) {
        background-color: #949494;
        width: 1%;
        height: 3%;
        transform: translate(-50%, -50%) rotate(354deg) translateY(-1461%);
    }

    .needle {
        position: absolute;
        top: 50%;
        left: 50%;
        transform-origin: center;
    }

    .needle#hours {
        background-color: #1f1f1f;
        width: 4%;
        height: 30%;
        transform-origin: center 75%;
        transform: translate(-50%, -75%);
    }

    .needle#hours.moving {
        transition: transform 150ms ease-out;
    }

    .needle#hours:after {
        content: '';
        background-color: #1f1f1f;
        width: 4vw;
        height: 4vw;
        max-width: 4vh;
        max-height: 4vh;
        display: block;
        position: absolute;
        top: 75%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }

    .needle#minutes {
        background-color: #1f1f1f;
        width: 2%;
        height: 45%;
        transform-origin: center 75%;
        transform: translate(-50%, -75%);
    }

    .needle#minutes.moving {
        transition: transform 150ms ease-out;
    }

    .needle#minutes:after {
        content: '';
        background-color: #1f1f1f;
        width: 4vw;
        height: 4vw;
        max-width: 4vh;
        max-height: 4vh;
        display: block;
        position: absolute;
        top: 75%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }

    .needle#seconds {
        background-color: #cb2f2f;
        width: 1%;
        height: 50%;
        transform-origin: center 75%;
        transform: translate(-50%, -75%);
    }

    .needle#seconds.moving {
        transition: transform 150ms ease-out;
    }

    .needle#seconds:after {
        content: '';
        background-color: #cb2f2f;
        width: 2.5vw;
        height: 2.5vw;
        max-width: 2.5vh;
        max-height: 2.5vh;
        display: block;
        position: absolute;
        top: 75%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }
    .clock_logo{
        width: 10vw;
        height: 10vw;
        max-width: 10vh;
        max-height: 10vh;
        position: absolute;
        top: 50%;
        left: 50%;
        box-sizing: border-box;
        border-radius: 50%;
        transform: translate(-50%, -50%);
        background-size: 100% 100%;
        background-repeat: no-repeat;
    }
    .clock_logo{
            width: 10vw;
            height: 10vw;
            max-width: 10vh;
            max-height: 10vh;
            position: absolute;
            top: 50%;
            left: 50%;
            box-sizing: border-box;
            border-radius: 50%;
            transform: translate(-50%, -50%);
            background-image: var(--clock-logo);
            background-size: 100% 100%;
            background-repeat: no-repeat;
    }
    @media (min-width: 100vh) {
        .clock {
            border: solid 2.8vh var(--color-primary);
            box-shadow: 0 1.4vh 2.8vh var(--color2);
        }
    }

</style>





            </div>
        
            <div class="nexmoe-pd-item">
                <div class="qweather" >
    <div id="he-plugin-standard">
        <iframe allowtransparency="true" frameborder="0" width="304" height="96" scrolling="no" src="//tianqi.2345.com/plugin/widget/index.htm?s=2&z=1&t=0&v=0&d=2&bd=0&k=000000&f=ff8040&ltf=009944&htf=cc0000&q=1&e=1&a=1&c=54511&w=300&h=96&align=center"></iframe>
    </div>
    <div class="qweather-logo">

    </div>
</div>
<style>
    .qweather{
        position: relative;
        padding-right: 5px;
    }
    .qweather #he-plugin-standard {
        border: 2px solid var(--color-primary);
        box-shadow: 0 1px 0 0 var(--color-primary), 0 1px 2px 0 var(--color-primary);
        border-radius: 8px;
        width: 300px;
        overflow: hidden;
    }
    .qweather-logo{
        position: absolute;
        right: 0;
        top: -15px;
        width: 40px;
        height: 40px;
        background-image: var(--qweather-logo);
        background-size: 100% 100%;
        background-repeat: no-repeat;
    }
</style>

            </div>
        
    
</div>
<style>
    .nexmoe-pd {
        left: auto;
        top: 40px;
        right: 0;
    }
    .nexmoe-pd-item{
       display: flex;
        justify-content: center;
        margin-bottom: 30px;
    }
    #nexmoe-pendant .mdui-drawer{
        width: 305px;
    }
    @media screen and (max-width: 1600px) {
        #nexmoe-pendant {
            display: none
        }
    }
</style>
</div><div id="nexmoe-footer"><!--!--></div><div id="nexmoe-search-space"><div class="search-container"><div class="search-header"><div class="search-input-container"><input class="search-input" type="text" placeholder="搜索" onInput="sinput();"></div><a class="search-close" onclick="sclose();">×</a></div><div class="search-body"></div></div></div><div></div><!-- hexo injector body_end start -->
<script src="https://cdn.jsdelivr.net/npm/hexo-shiki-plugin@latest/lib/codeblock.js"></script>

  <script>
  const CODE_CONFIG = {
    beautify: true,
    highlightCopy: true,
    highlightLang: true,
    highlightHeightLimit: null,
    isHighlightShrink: false,
    copy: {
      success: 'Copy Success',
      error: 'Copy Error',
      noSupport: 'Browser Not Support',
    }
  };
  console.log(
    `%c hexo-shiki-plugin %c v1.0.27 %c https://github.com/nova1751/hexo-shiki-plugin`,
    "color: #fff; background: #5f5f5f",
    "color: #fff; background: #80c8f8",
    ""
  );
  </script>
  <!-- hexo injector body_end end --><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/xiaomai.model.json"},"display":{"position":"left","width":200,"height":500},"mobile":{"show":false},"react":{"opacity":0.9},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body></html>